##
# Tile
# Description: A tile of the map and it's properties
#
# Attributes:
#   blocked - whether or not the tile blocks movement (boolean)
#   blockSight - whether or not the tile blocks sigh (boolean)
##
class Tile:
    def __init__(self, blocked, blockedSight=None):
        self.blocked = blocked
        if blockedSight is None: blockedSight = blocked
        self.blockedSight = blockedSight
        self.explored = False

        self.stack = []

    ##
    # add_object
    #
    # Description: Add a object to the tile
    #
    # Parameters:
    #   stack_position - Order that things are stacked, 0 is lowest to the ground.
    #       Use negative numbers to add relative to the top where -1 would be add to the top
    #   new_object - the object to add to the stack
    #
    def add_object(self, new_object, stack_position=-1):
        self.stack.insert(self._get_insert_position(stack_position), new_object)

    ##
    # remove_object
    #
    # Description: removes an object from the stack
    #
    # Parameters:
    #   object_to_remove - the object to remove
    def remove_object(self, object_to_remove):
        while self.stack.count(object_to_remove) > 0:
            self.stack.remove(object_to_remove)

    ##
    # _get_insert_position
    #
    # Description: gets the index to insert the a new object into the stack with.
    #   Follows These Rules:
    #   0 is lowest to the ground.
    #   Negative Numbers to add relative to the top. (-1 adds to the top)
    #
    # Parameters:
    #   stack_position - the desired position in the stack
    #
    # Returns: the index position to be used with stack.insert
    def _get_insert_position(self, stack_position):
        insert_pos = stack_position
        if stack_position < 0:
            insert_pos = len(self.stack) + stack_position

            # if still negative after adding the length then place it close to the ground
            if insert_pos < 0:
                insert_pos = 0

        return insert_pos

    ##
    # touch_objects
    #
    # Description: Calls on_touch on all objects in the stack using the same arguments as this function
    #
    # Parameters:
    #   toucher - the object which touched the others
    #
    def touch_objects(self, toucher):

        for touched in self.stack:
            if hasattr(touched, "on_touch"):
                touched.on_touch(toucher)

        return

    def is_passable(self):

        if self.blocked:
            return False

        for obj in self.stack:
            # is their an object blocking the tile?
            if obj.blocks:
                return False

        return True
